
	/***********************************************************************************************
	  
		Module: Locale
		
		Methods:
			mod		use					(id*)				- sid: 5.0
			mod		set					(id, data)	- sid: 5.0
			data	get					(id*)				- sid: 5.0
			id		getCurrent	()					- sid: 5.0
			a			list				()					- sid: 5.0
			b			isDefined		(id)				- sid: 5.0
					
		Events:
			beforeChange, change
		
		Note:
			supported locale ids ex: en-us, de, it_IT ... 
		
		Data legend:																																				
													required		default
													----------------------------------------------------
			+Date
			d_days								y
			d_days_short					-						first three letters of days
			d_days_ordinals				-						""
			d_months							y
			d_months_short				-						first three letters of months																											
			d_am									-						"AM"
			d_pm									-						"PM"																		
			d_formats							y						-
			d_first_wday					-						0
			d_tzs									y						-			
			
			+Number
			n_sep_dec							-						"."
			n_sep_zero						-						","
			n_format							-						null
			
			+Language
			l_lang								-						locale id
																																											
	************************************************************************************************/
		
	//Module init
	//-------------------------------------------------------------------------------
	jsl.Locale = (function() {
		try {
			var mod

			mod					= new jsl.Module("jsl.Locale")
			mod.__c			= null
			mod.__ls		= {}
					
			mod.addEvents("beforeChange", "change")			
			mod.setEventAction("change", function(e) { jsl.console.debug("locale.Change", e.old_locale + " -> " + e.new_locale) })
			
			return mod
		}
		catch(e) {
			jsl.throwError(e, "jsl.Locale()")			
		}
	})()
	
	//-------------------------------------------------------------------------------
	jsl.Locale.use = function(id) {
		try {
			var nl, e
			
			//@d[
			if(arguments.length > 1)	throw jsl.ParamError()
			if(arguments.length)			jsl.validate(id, "s+", "id")//@d]
			
			nl = id ? this.__normalize(id) : this.__ni_locale_get()
			
			if(nl !== this.__c) {
				
				e = new jsl.Event({ old_locale: this.__c, new_locale: nl })				
				this.throwEvent("beforeChange", e)
	
				this.__c = nl
				
				this.throwEvent("change", e)
			}
			
			return this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.set = function(id, data) {
		try {
			var ts, o, pid, l, ll, dn, d, from, a, len
			var clone, merge

			//@d[
			if(arguments.length !== 2)	throw jsl.ParamError()			
			jsl.validate(id, "sr/\\w+(\\-\\w+)?(:\\w+(\\-\\w+)?)?(\\.[\\w]+)?", "id")//@d] 
			
			ts		= id.split(":")
			from	= ts.length > 1 ? this.__normalize(ts[0]) : ""
			l			= this.__normalize((ts.length > 1 ? ts[1] : ts[0]).split(".")[0])
			pid		= id.split(".")[1]
			o 		= !pid
			dn		= o ? "data." : ""
			clone	= jsl.Object.clone	
			merge	= jsl.Object.merge		
						
			//@d[
			if(from && !this.__ls[from])	throw jsl.ParamError("NotDefined:id(from)")	
			if(from === l)								throw jsl.ParamError("BadValue:id")			
			if(o)													jsl.validate(data, "o", "data")
			else if(!this.__ls[l])				throw jsl.ParamError("NotDefined:id(" + l + ")")
			//@d]
			
			if(o) {			
				if(from)					d = clone(this.__ls[from], 1)
				if(this.__ls[l])	d = d ? merge(d, this.__ls[l]) : clone(this.__ls[l], 1)	
				
				d = d ? merge(d, data) : clone(data, 1)		
			}
			else
				(d = {})[pid] = jsl.Object.clone(data, 1)
			
			//@d[
			if(o || pid === "d_days")		jsl.validate(d.d_days		, "al", dn + "d_days")
			if(o || pid === "d_months")	jsl.validate(d.d_months	, "al", dn + "d_months")//@d]
								
			//default values			
			//-------------------------------------------------------------------------------
			if(o && !this.__ls[l]) {
				
				if(!d.d_days_short)	{ 
					
					d.d_days_short = []
					for(a = 0, len = d.d_days.length; a < len; a++)  
						d.d_days_short[a] = d.d_days[a].slice(0, 3)
				}		
				
				if(!d.d_months_short)	{ 
					
					d.d_months_short = []
					for(a = 0, len = d.d_months.length; a < len; a++)  
						d.d_months_short[a] = d.d_months[a].slice(0, 3)
				}		
				
				if(!d.d_formats) 
					d.d_formats = { date: "yyyy/mmy/dd", date_long: "Month d, yyyy", month_day: "Month dd", month_year: "Month, yyyy" }
								
				if(!d.d_days_ordinals)		d.d_days_ordinals = ["??"]
				if(!d.d_first_wday)				d.d_first_wday = 0
				if(!d.d_am)								d.d_am = "AM"
				if(!d.d_pm)								d.d_pm = "PM"

				if(!d.n_sep_dec)					d.n_sep_dec 	= "."
				if(!d.n_sep_zero)					d.n_sep_zero 	= ","

				if(!data.l_lang)					d.l_lang = l
			}

			//@d[						

			//date 
			//-------------------------------------------------------------------------------
			if(o || pid === "d_days_short")				jsl.validate(d.d_days_short 			, "al"		, dn + "d_days_short")
			if(o || pid === "d_months_short")			jsl.validate(d.d_months_short			, "al"		, dn + "d_months_short")
			if(o || pid === "d_formats")					jsl.validate(d.d_formats					, "o"			, dn + "d_formats")
			if(o || pid === "d_days_ordinals")		jsl.validate(d.d_days_ordinals		, "al"		, dn + "d_days_ordinals")
			if(o || pid === "d_first_wday")				jsl.validate(d.d_first_wday				, "i[0,6]", dn + "d_first_wday")
			if(o || pid === "d_am")								jsl.validate(d.d_am								, "s"			, dn + "d_am")
			if(o || pid === "d_pm")								jsl.validate(d.d_pm		 						, "s"			, dn + "d_pm")
			if(o || pid === "d_tzs")							jsl.validate(d.d_tzs							, "o"			, dn + "d_tzs")
			
			//sub-contents
			if(o || pid === "d_days")
			for(a = 0, len = d.d_days.length; a < len; a++)	jsl.validate(d.d_days[a], "s+", dn + "d_days[" + a + "]")

			if(o || pid === "d_days_short")
			for(a = 0, len = d.d_days_short.length;	a < len; a++)	jsl.validate(d.d_days_short[a], "s+", dn + "d_days_short[" + a + "]")

			if(o || pid === "d_months")
			for(a = 0, len = d.d_months.length; a < len; a++)	jsl.validate(d.d_months[a], "s+", dn + "d_months[" + a + "]")

			if(o || pid === "d_months_short")
			for(a = 0, len = d.d_months_short.length;	a < len; a++)	jsl.validate(d.d_months_short[a], "s+", dn + "d_months_short[" + a + "]")

			if(o || pid === "d_formats") {
        jsl.validate(d.d_formats.date				, "f|s+", dn + "d_formats.date")
        jsl.validate(d.d_formats.date_l			, "f|s+", dn + "d_formats.date_l")
        jsl.validate(d.d_formats.time				, "f|s+", dn + "d_formats.time")
        jsl.validate(d.d_formats.time_l			, "f|s+", dn + "d_formats.time_l")
        jsl.validate(d.d_formats.month_day	, "f|s+", dn + "d_formats.month_day")
        jsl.validate(d.d_formats.month_year	, "f|s+", dn + "d_formats.month_year")
			}
							
			if(o || pid === "d_days_ordinals")
			for(a = 0, len = d.d_days_ordinals.length ; a < len; a++)	
				if(d.d_days_ordinals[a] != null)
					jsl.validate(d.d_days_ordinals[a], "s+", dn + "d_days_ordinals[" + a + "]")						

			if(o || pid === "d_tzs")
				for(a in d.d_tzs)
					if(d.d_tzs.hasOwnProperty(a)) {	
						jsl.validate(a					, "sr/^\\-?\\d{1,3}$"	, dn + "d_tzs[" + a + "]")
						jsl.validate(d.d_tzs[a]	, "sr/^\\w+(:\\w+)?$"	, dn + "d_tzs["	+ d.d_tzs[a] + "]")					
					}
					
			//numbers
			//-------------------------------------------------------------------------------
			if(o || pid === "n_sep_dec")	jsl.validate(d.n_sep_dec	, "s+", dn + "n_sep_dec")
			if(o || pid === "n_sep_zero")	jsl.validate(d.n_sep_zero	, "s+", dn + "n_sep_zero")
			
			if(d.n_format)
			if(o || pid === "n_format")		jsl.validate(d.n_format	, "f"	, dn + "n_format")			

			//language			
			//-------------------------------------------------------------------------------
			if(o || pid === "l_lang")	jsl.validate(d.l_lang, "s+", dn + "l_lang")
			//@d]
			
			if(o)	{					
				this.__ls[l] 		= d				
				this.__ls[l].id = l
			}
			else
				this.__ls[l][pid]	= d[pid]

			return this
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.get = function(id) {
		try {
			var lid
			
			//@d[
			if(arguments.length > 1)								throw jsl.ParamError()			
			if(arguments.length)										jsl.validate(id, "s+", "id")//@d]
			
			if(id) lid = this.__normalize(id)
			//@d[
			if(arguments.length && !this.__ls[lid])	throw jsl.ParamError("NotDefined:id")//@d]
			
			
			if(!id && !this.__c) 
				this.getCurrent()

			return jsl.Object.clone(this.__ls[id ? lid : this.__c], 1)
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.getCurrent = function() {
		try {			
			//@d[
			if(arguments.length)	throw jsl.ParamError()//@d]
			
			if(!this.__c) { 
				this.__c = this.__ni_locale_get()//@d[	
				if(!this.__ls[this.__c])	throw jsl.ParamError("locale.NotDefined:" + this.__c)//@d]
			}
			
			return this.__c
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.list = function() {
		try {
			var l = []
			
			//@d[
			if(arguments.length)	throw jsl.ParamError()//@d]
			
			for(var id in this.__ls)
				if(this.__ls.hasOwnProperty(id))
					l.push(id)
			
			return l
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.isDefined = function(id) {
		try {
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(id, "s+", "id")
			//@d]
						
			return !!this.__ls[this.__normalize(id)]
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Locale.__normalize = function(id) {
		try {	
			var nid
			
			if(id.indexOf("-") 			!== -1) nid = id + ""
			//some locales have awkward ids ex: kk_Cyrl
			else if(id.indexOf("_") !== -1) nid = id.replace(/(_)[^_]+$/, "&1")
			else														nid = id + "-" + id					
			return nid.toLowerCase()
		}
		catch(e) {
			jsl.throwError(e, this, arguments)					
		}
	}
		
	//eng-us
	//-------------------------------------------------------------------------------
	jsl.Locale.set("en-us", {
		
		d_days:						[	"Sunday", "Monday", "Tuesday"	, "Wednesday", "Thursday", "Friday", "Saturday" ],		
		d_months: 				[
												"January"	, "February", "March"			, "April"		, "May"			, "June", 
												"July"		, "August"	, "September"	, "October"	, "November", "December"
											],
														
		d_days_ordinals:	[ "th", "st", "nd", "rd",,,,,,,,,,,,,,,,,, "st", "nd", "rd" ],
		
		d_formats:				{
												date: 			"m/d/yyyy",
												date_l:			"Day, Month d, yyyy",
												time:				"h:mmn MR",
												time_l:			"h:mmn:ss MR",
												month_day:	"Month d",
												month_year:	"Month, yyyy"
											},
											
		d_tzs:						{ 
												"-600": 	"HAST:HADT", 
												"-540": 	"AKST:AKDT", 
												"-480": 	"PST:PDT", 
												"-420": 	"MST:MDT", 
												"-360": 	"CST:CDT", 
												"-300": 	"EST:EDT"
											}
	})

	//eng-gb
	//-------------------------------------------------------------------------------
	jsl.Locale.set("en-us:en-gb", { 
		
		d_formats:				{
												date: 			"dd/mm/yyyy",
												date_l:			"dd Month yyyy",
												time:				"HH:mmn",
												time_l:			"HH:mmn:ss",
												month_day:	"d Month",
												month_year:	"Month yyyy"
											},
		d_first_wday: 		1,
		d_tzs:						{ "0": "GMT:BST" }
	})
	
	//de-de
	//-------------------------------------------------------------------------------
	jsl.Locale.set("de", {
		
		d_days:						[ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag"	, "Samstag" ],		
		d_months: 				[
												"Januar"	, "Februar"	, "März"			, "April"		, "Mai"			, "Juni", 
												"Juli"		, "August"	, "September"	, "Oktober"	, "November", "Dezember"
											],

		d_formats:				{
												date: 			"dd.mm.yyyy",
												date_l:			"Day, d. Month yyyy",
												time:				"HH:mmn",
												time_l:			"HH:mmn:ss",
												month_day:	"d Month",
												month_year:	"Month yyyy"
											},
											
		d_first_wday: 		1,
		d_tzs:						{ "60":	"CET:CEST" },																
		
		n_sep_dec:				",",
		n_sep_zero:				"."
	})
		
	//fr-fr
	//-------------------------------------------------------------------------------
	jsl.Locale.set("fr", {
		
		d_days:						[	"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi" ],		
		d_months: 				[
												"Janvier"	, "Février"	, "Mars"			, "Avril"		, "Mai"			, "Juin", 
												"Juillet"	, "Août"		, "Septembre"	, "Octobre"	, "Novembre", "Décembre"
											],
										
		d_formats:				{
												date: 			"dd/mm/yyyy",
												date_l:			"Day d Month yyyy",
												time:				"HH:mmn",
												time_l:			"HH:mmn:ss",
												month_day:	"d Month",
												month_year:	"Month yyyy"
											},
											
		d_first_wday: 		1,
		d_tzs:						{ "60":	"CET:CEST" },																
		
		n_sep_dec:				",",
		n_sep_zero:				" "
	})

	//it-it
	//-------------------------------------------------------------------------------
	jsl.Locale.set("it", {
		
		d_days:						[	"Domenica", "Lunedì"	, "Martedì"	, "Mercoledì", "Giovedì"	, "Venerdì"	, "Sabato" ],		
		d_months: 				[
												"Gennaio"	, "Febbraio", "Marzo"			, "Aprile"	, "Maggio"		, "Giugno", 
												"Luglio"	, "Agosto"	, "Settembre"	, "Ottobre"	, "Novembre"	, "Dicembre"
											],

		d_formats:				{ 
												date: 			"dd/mm/yyyy",
												date_l: 		"day d month yyyy",
												time:				"H.mmn",
												time_l:			"H.mmn.ss",
												month_day:	"d Month",
												month_year: "Month yyyy"
											},	
												
		d_first_wday: 		1,		
		d_tzs:						{ "60":	"CET:CEST" },		
		
		n_sep_dec:				",",
		n_sep_zero:				"."
	})

	//it-ch
	//-------------------------------------------------------------------------------
	jsl.Locale.set("it:it-ch", {
		
		d_formats:				{ 
												date: 			"dd.mm.yyyy",
												date_l: 		"day, d. month yyyy",
												time:				"HH.mmn",
												time_l:			"HH.mmn.ss",
												month_day:	"d. Month",
												month_year: "Month yyyy"
											},	
												
		n_sep_dec:				".",
		n_sep_zero:				"'"
	})

	//es-es
	//-------------------------------------------------------------------------------
	jsl.Locale.set("es", {
		
		d_days:						[ "Domingo", "Lunes", "Martes"	, "Miércoles", "Jueves"	, "Viernes"	, "Sábado" ],		
		d_months: 				[
												"Enero"		, "Febrero"	, "Marzo"			, "Abril"		, "Mayo"			, "Junio", 
												"Julio"		, "Agosto"	, "Septiembre", "Octubre"	, "Noviembre"	, "Diciembre"
											],
												
		d_formats:				{	 
												date: 			"dd/mm/yyyy",
												date_l: 		"Day, dd de Month de yyyy",
												time:				"H:mmn",
												time_l:			"H:mmn:ss",
												month_day:	"dd Month",
												month_year: "Month de yyyy"
											},	
												
		d_first_wday: 		1,		
		d_tzs:						{ "60":	"CET:CEST" },		
		
		n_sep_dec:				",",
		n_sep_zero:				"."
	})

	//es-ar
	//-------------------------------------------------------------------------------
	jsl.Locale.set("es:es-ar", {
	
		
		d_formats:				{	 
												date: 			"dd/mm/yyyy",
												date_l: 		"Day, dd de Month de yyyy",
												time:				"h:mmn",
												time_l:			"h:mmn:ss",
												month_day:	"dd Month",
												month_year: "Month de yyyy"
											},	
												
		d_first_wday: 		0,	
		d_am:							"a.m.",
		d_pm:							"p.m.",	
		
		//dst is ruled year-by-year and can be different from differents federal regions
		d_tzs:						{ "-180":	"ART:ARDT" }
	})

	//pl-pl
	//-------------------------------------------------------------------------------
	jsl.Locale.set("pl", {
		
		d_days:						[	"Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota" ],		
		d_days_short:			[ "N", "Pn", "Wt", "Śr", "Cz", "Pt", "So" ],
		d_months: 				[
												"Styczeń"	, "Luty"				, "Marzec"	, "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", 
												"Wrzesień", "Październik"	, "Listopad", "Grudzień"
											],
												
		d_formats:				{	 
												date: 			"yyyy-mm-dd",
												date_l: 		"d Month yyyy",
												time:				"HH:mmn",
												time_l:			"HH:mmn:ss",
												month_day:	"d Month",
												month_year: "Month yyyy"
											},	
												
		d_first_wday: 		1,		
		d_tzs:						{ "60":	"CET:CEST" },		
		
		n_sep_dec:				",",
		n_sep_zero:				" "
	})
						